﻿using FastUtil.Config;
using FastUtil.Log;
using Quartz;
using Quartz.Impl;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace FastUtil.Extra
{
    public class QuartzUtil
    {
        private static IScheduler Scheduler;

        private static string CustomerQuartzClassInfo;

        public static void InitPlugin(string CustomerQuartzPlugin)
        {
            CustomerQuartzClassInfo = CustomerQuartzPlugin;
        }

        public static async Task<IScheduler> GetScheduler()
        {
            var properties = new System.Collections.Specialized.NameValueCollection();
            //自定义Plugin 命名空间.类名,程序名称
            properties["quartz.plugin.MyPlugin.type"] = CustomerQuartzClassInfo;
            if (null == Scheduler)
            {
                ISchedulerFactory schedulerFactory = new StdSchedulerFactory(properties);
                Scheduler = await schedulerFactory.GetScheduler();
            }
            return Scheduler;
        }

        public static ITrigger GetCycleTrigger(string TaskName, string TaskTag, int TaskExecutePeriod, int TaskExecuteUnit)
        {
            TriggerBuilder builder = TriggerBuilder.Create().WithIdentity(TaskName, TaskTag);
            if (TaskExecutePeriod == 0)
            {
                //如果设置为0，则无间断执行，因为Quartz间隔不能设置为0，这里设置为一毫秒
                TimeSpan span = new TimeSpan(0, 0, 0, 0, 1);
                builder.WithSimpleSchedule(t =>
                 t.RepeatForever().WithInterval(span));
            }
            else
            {
                switch (TaskExecuteUnit)
                {
                    case 300:
                        builder.WithSimpleSchedule(t =>
                   t.RepeatForever().WithIntervalInHours(TaskExecutePeriod));
                        break;
                    case 200:
                        builder.WithSimpleSchedule(t =>
                  t.RepeatForever().WithIntervalInMinutes(TaskExecutePeriod));
                        break;
                    case 100:
                        builder.WithSimpleSchedule(t =>
                  t.RepeatForever().WithIntervalInSeconds(TaskExecutePeriod));
                        break;
                }
            }
            ITrigger trigger = builder.Build();
            return trigger;
        }

        public static ITrigger GetCornTrigger(string TaskName, string TaskTag, string CornExplain)
        {
            TriggerBuilder builder = TriggerBuilder.Create().WithIdentity(TaskName, TaskTag);
            builder.WithCronSchedule(CornExplain);
            ITrigger trigger = builder.Build();
            return trigger;
        }

        public static async Task<bool> PauseJob(string TaskName, string TaskTag)
        {
            try
            {
                IScheduler scheduler = await GetScheduler();
                TriggerKey triggerkey = new TriggerKey(TaskName, TaskTag);
                await scheduler.PauseJob(scheduler.GetTrigger(triggerkey).Result.JobKey);
                return true;
            }
            catch (Exception e)
            {
                StringBuilder builder = new StringBuilder();
                builder.AppendFormat("PauseJob发生错误!" + Environment.NewLine);
                builder.AppendFormat("异常信息:{0}", e.Message + Environment.NewLine);
                builder.AppendFormat("堆栈信息:{0}", e.StackTrace + Environment.NewLine);
                LogUtil.WriteLog(PathUtil.GetContentPath() + "/Logs/QuartzUtil", "log_pausejob_", builder.ToString());
                return false;
            }
        }

        public static async Task<bool> ResumeJob(string TaskName, string TaskTag)
        {
            try
            {
                IScheduler scheduler = await GetScheduler();
                TriggerKey triggerkey = new TriggerKey(TaskName, TaskTag);
                await scheduler.ResumeJob(scheduler.GetTrigger(triggerkey).Result.JobKey);
                return true;
            }
            catch (Exception e)
            {
                StringBuilder builder = new StringBuilder();
                builder.AppendFormat("ResumeJob发生错误!" + Environment.NewLine);
                builder.AppendFormat("异常信息:{0}", e.Message + Environment.NewLine);
                builder.AppendFormat("堆栈信息:{0}", e.StackTrace + Environment.NewLine);
                LogUtil.WriteLog(PathUtil.GetContentPath() + "/Logs/QuartzUtil", "log_resumejob_", builder.ToString());
                return false;
            }
        }

        public static async Task<bool> RemoveJob(string TaskName, string TaskTag)
        {
            try
            {
                IScheduler scheduler = await GetScheduler();
                TriggerKey triggerkey = new TriggerKey(TaskName, TaskTag);
                //停止job
                await scheduler.ResumeJob(scheduler.GetTrigger(triggerkey).Result.JobKey);
                //删除相关的job任务 
                await scheduler.DeleteJob(scheduler.GetTrigger(triggerkey).Result.JobKey);
                return true;
            }
            catch (Exception e)
            {
                StringBuilder builder = new StringBuilder();
                builder.AppendFormat("RemoveJob发生错误!" + Environment.NewLine);
                builder.AppendFormat("异常信息:{0}", e.Message + Environment.NewLine);
                builder.AppendFormat("堆栈信息:{0}", e.StackTrace + Environment.NewLine);
                LogUtil.WriteLog(PathUtil.GetContentPath() + "/Logs/QuartzUtil", "log_removeJob_", builder.ToString());
                return false;
            }
        }

        public static async Task<bool> StartJob(int TaskType, string TaskName, string TaskTag, string JobClassName, int TaskExecutePeriod, int TaskExecuteUnit, string CornExplain)
        {
            try
            {
                IScheduler scheduler = await GetScheduler();
                TriggerKey triggerkey = new TriggerKey(TaskName, TaskTag);
                ITrigger trigger = await scheduler.GetTrigger(triggerkey);
                if (null != trigger && await scheduler.CheckExists(triggerkey))
                {
                    //如果有这个job，说明是暂停的任务，重启即可
                    await ResumeJob(TaskName, TaskTag);
                }
                else
                {
                    //没有这个job，说明是新增的，或者是停止后开启的
                    JobDataMap jobData = new JobDataMap();
                    jobData.Add("TaskName", TaskName);
                    jobData.Add("TaskTag", TaskTag);
                    IJobDetail job = JobBuilder.Create(Type.GetType(JobClassName)).SetJobData(jobData).Build();
                    //如果是停止的job，先暂停trigger
                    if (await scheduler.CheckExists(triggerkey))
                    {
                        await scheduler.PauseTrigger(triggerkey);
                        await scheduler.ScheduleJob(job, trigger);
                        //重启触发器  
                        await scheduler.ResumeTrigger(triggerkey);
                    }
                    else
                    {
                        //新增trigger
                        await scheduler.PauseTrigger(triggerkey);
                        if (TaskType == 100)
                        {
                            //循环任务
                            trigger = GetCycleTrigger(TaskName, TaskTag, TaskExecutePeriod, TaskExecuteUnit);
                        }
                        else
                        {
                            //表达式任务
                            trigger = GetCornTrigger(TaskName, TaskTag, CornExplain);
                        }

                        await scheduler.ScheduleJob(job, trigger);
                    }
                }

                return true;
            }
            catch (Exception e)
            {
                StringBuilder builder = new StringBuilder();
                builder.AppendFormat("StartJob发生错误!" + Environment.NewLine);
                builder.AppendFormat("异常信息:{0}", e.Message + Environment.NewLine);
                builder.AppendFormat("堆栈信息:{0}", e.StackTrace + Environment.NewLine);
                LogUtil.WriteLog(PathUtil.GetContentPath() + "/Logs/QuartzUtil", "log_startjob_", builder.ToString());
                return false;
            }
        }

        public static async Task<bool> CloseScheduler()
        {
            try
            {
                IScheduler scheduler = await GetScheduler();
                if (scheduler.IsStarted)
                {
                    await scheduler.PauseAll();
                    await scheduler.Clear();
                    await scheduler.Shutdown(true);
                }
            }
            catch (Exception)
            {
                return false;
            }
            return true;
        }
    }
}
